package gui;

import java.awt.Dimension;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Date;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JOptionPane;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

import com.toedter.calendar.JDateChooser;
import com.zaverka.util.dialogs.ElementValidation;
import com.zaverka.util.dialogs.FormDialog;

import core.Profile;
import core.Transaction;
import core.TransactionDirection;

public class TransactionDialogs
{
	private static TransactionDialogs singleton;
	private static Window currentParent;
	
	public static Transaction newTransaction(Window parent, Profile profile){
		initialize(parent);
		return singleton.showNewTransaction(profile);
	}

	public static boolean editTransaction(Transaction transaction, Window parent, Profile profile){
		initialize(parent);
		return singleton.showEditTransaction(transaction, profile);
	}

	public static boolean deleteTransaction(Transaction transaction, Window parent){
		int result = JOptionPane.showConfirmDialog(parent, "Opravdu chcete zrušit transakci?", "Potvrzení", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
		return result == JOptionPane.YES_OPTION;
	}
	
	private static void initialize(Window parent){
		if(singleton == null || parent != currentParent){
			singleton = new TransactionDialogs(parent);
			currentParent = parent;
		}
	}
	
	private FormDialog dialog;
	
	private JRadioButton incomeSelection, expenseSelection;
	private JComboBox typeField;
	private JDateChooser dateField;
	private JTextField ammountField;
	private JTextArea commentField;
	
	private Profile currentProfile;
	
	private TransactionDialogs(Window parent){
		dialog = new FormDialog("", parent, true);
		dialog.setErrorMessageLabel("Chyba");
		dialog.setCancelButtonLabel("Zrušit");
		
		Box directionSelection = new Box(BoxLayout.X_AXIS);
		directionSelection.add(Box.createHorizontalGlue());
		ButtonGroup group = new ButtonGroup();
		incomeSelection = new JRadioButton("Příjem");
		incomeSelection.addActionListener(new LoadTypesListener(TransactionDirection.INCOME));
		group.add(incomeSelection);
		directionSelection.add(incomeSelection);
		directionSelection.add(Box.createHorizontalGlue());
		expenseSelection = new JRadioButton("Výdaj");
		expenseSelection.addActionListener(new LoadTypesListener(TransactionDirection.EXPENSE));
		expenseSelection.setSelected(true);
		group.add(expenseSelection);
		directionSelection.add(expenseSelection);
		directionSelection.add(Box.createHorizontalGlue());
		
		dialog.addElement("", directionSelection);
		typeField = new JComboBox();
		typeField.setEditable(true);
		dialog.addElement("Typ", typeField, new TypeValidation());
		dateField = new JDateChooser(new Date());
		dateField.addPropertyChangeListener(new DateFocusChanger());
		dialog.addElement("Datum", dateField);
		ammountField = new JTextField();
		dialog.addElement("Částka", ammountField, "\\d{1,9}([\\x2c\\x2e]\\d{1,2})?", "Zadaná částka musí být číslo");
		commentField = new JTextArea();
		dialog.setElementPreferredSize(new Dimension(300, 35));
		dialog.addElement("Poznámka", new JScrollPane(commentField));
	}
	
	private Transaction showNewTransaction(Profile profile){
		currentProfile = profile;
		dialog.setTitle("Nová transakce");
		loadTypesBox(TransactionDirection.EXPENSE);
		clearForms();
		Transaction newTransaction = null;
		boolean result = dialog.showDialog();
		
		if(result){
			TransactionDirection direction = incomeSelection.isSelected() ? 
						TransactionDirection.INCOME : TransactionDirection.EXPENSE;
			String type = typeField.getSelectedItem().toString();
			Date date = dateField.getDate();
			double ammount = Double.parseDouble(ammountField.getText());
			String comment = commentField.getText();
			newTransaction = new Transaction(ammount, comment, type, direction, date);
		}
		return newTransaction;
	}
	
	private boolean showEditTransaction(Transaction transaction, Profile profile){
		currentProfile = profile;
		dialog.setTitle("Editace transakce");
		loadTypesBox(transaction.getDirection());
		incomeSelection.setSelected(transaction.getDirection() == TransactionDirection.INCOME);
		expenseSelection.setSelected(transaction.getDirection() == TransactionDirection.EXPENSE);
		incomeSelection.setEnabled(false);
		expenseSelection.setEnabled(false);
		typeField.setSelectedItem(transaction.getType());
		dateField.setDate(transaction.getDate());
		ammountField.setText(String.valueOf(transaction.getAmmount()));
		commentField.setText(transaction.getDescription());
		
		boolean edited = dialog.showDialog();
		
		if(edited){
			String type = typeField.getSelectedItem().toString();
			Date date = dateField.getDate();
			double ammount = Double.parseDouble(ammountField.getText());
			String comment = commentField.getText();
			transaction.setType(type);
			transaction.setDate(date);
			transaction.setAmmount(ammount);
			transaction.setDescription(comment);
		}
		return edited; 
	}
	
	private void clearForms(){
		typeField.setSelectedItem("");
		dateField.setDate(new Date());
		ammountField.setText("");
		commentField.setText("");
		expenseSelection.setSelected(true);
		incomeSelection.setEnabled(true);
		expenseSelection.setEnabled(true);
	}

	private void loadTypesBox(TransactionDirection direction){
		Object[] newData = currentProfile.getData().getUsedTypes(direction).toArray();
		typeField.setModel(new DefaultComboBoxModel(newData));
		typeField.setSelectedItem("");
	}
	
	private class LoadTypesListener implements ActionListener
	{
		private TransactionDirection direction;
		
		private LoadTypesListener(TransactionDirection direction){
			this.direction = direction;
		}
		
		@Override public void actionPerformed(ActionEvent ae){
			loadTypesBox(direction);
		}
	}
	
	private class TypeValidation implements ElementValidation
	{
		@Override public String getErrorMessage(){
			return "Typ musí být zadán!";
		}

		@Override public boolean validate(){
			return typeField.getSelectedItem().toString().matches(".+");
		}
	}
	
	private class DateFocusChanger implements PropertyChangeListener
	{
		@Override public void propertyChange(PropertyChangeEvent evt){	
			ammountField.requestFocus();
			ammountField.setSelectionStart(0);
			ammountField.setSelectionEnd(ammountField.getText().length());
		}
	}
}
